/*********************\
 * file:     Main
 * version:  0.1a
 * package:  lwjgltest
 * 
 * author:   linus
 * team:     NexT
 * license:  -
\*********************/

package JnRTest;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.util.glu.GLU.*;

import java.io.IOException;
import java.util.ArrayList;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.lwjgl.LWJGLException;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.Display;

public class Main {
  public static int DISPLAY_HEIGHT = 480;
  public static int DISPLAY_WIDTH = 640;
  public static final Logger LOGGER = Logger.getLogger(Main.class.getName());

  public int squareSize;
  public int squareX;
  public int squareY;
  public int squareZ;
  public double vsp;
  public double hsp;
  public boolean ground=false,c_left=false,c_right=false,c_top=false;
  public ArrayList<Rectangle> rects;
  boolean k_space,k_left,k_right;
  static {
    try {LOGGER.addHandler(new FileHandler("errors.log",true));
    }catch(IOException ex){LOGGER.log(Level.WARNING,ex.toString(),ex);}
  }

  public static void main(String[] args) {
    Main main = null;
    try {
      main = new Main();
      main.create();
      main.run();
    }
    catch(Exception ex) {LOGGER.log(Level.SEVERE,ex.toString(),ex);}
    finally {if(main != null)main.destroy();}
  }

  public Main() {
    rects = new ArrayList();
    squareSize = 50;
    squareX = 100;
    squareY = 200;
    squareZ = 0;
    vsp=0;
    hsp=0;
  }

  public void create() throws LWJGLException {
    //Display;
    Display.setFullscreen(true);
    Display.setTitle("LWJGL TEST");
    Display.create();
    DISPLAY_WIDTH = Display.getDisplayMode().getWidth();
    DISPLAY_HEIGHT = Display.getDisplayMode().getHeight();

    //add blocks
    rects.add(new Rectangle(50,50,200,50));
    rects.add(new Rectangle(250,100,200,50));
    rects.add(new Rectangle(0,0,DISPLAY_WIDTH,25));

    //INPUT
    Keyboard.create();
    Mouse.setGrabbed(false);
    Mouse.create();

    initGL();
    resizeGL();
  }

  public void destroy() {
    //Methods already check if created before destroying.
    Mouse.destroy();
    Keyboard.destroy();
    Display.destroy();
  }

  public void initGL() {
    //2D Initialization
    glClearColor(0.0f,0.0f,0.0f,0.0f);
    glDisable(GL_DEPTH_TEST);
    glDisable(GL_LIGHTING);
    glPolygonMode ( GL_FRONT_AND_BACK, GL_LINE ) ; //Wireframe mode
  }

  public void processKeyboard(){
    k_space=Keyboard.isKeyDown(Keyboard.KEY_SPACE);
    k_left =Keyboard.isKeyDown(Keyboard.KEY_LEFT);
    k_right=Keyboard.isKeyDown(Keyboard.KEY_RIGHT);
  }

  public void processMouse() {
    //squareX = Mouse.getX();
    //squareY = Mouse.getY();
  }

  public void render() {
    glClear(GL_COLOR_BUFFER_BIT);
    glLoadIdentity();

    for(int i=0;i<rects.size();i++){
        rects.get(i).draw();
    }
    glPushMatrix();
    glTranslatef(squareX,squareY,0.0f);
    glColor3f(0.0f,0.5f,0.5f);
    glBegin(GL_QUADS);
      glTexCoord2f(0.0f,0.0f); glVertex2f(0.0f,0.0f);
      glTexCoord2f(1.0f,0.0f); glVertex2f(squareSize,0.0f);
      glTexCoord2f(1.0f,1.0f); glVertex2f(squareSize,squareSize);
      glTexCoord2f(0.0f,1.0f); glVertex2f(0.0f,squareSize);
    glEnd();
    glPopMatrix();
  }

  public void resizeGL() {
    //2D Scene
    glViewport(0,0,DISPLAY_WIDTH,DISPLAY_HEIGHT);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0.0f,DISPLAY_WIDTH,0.0f,DISPLAY_HEIGHT);
    glPushMatrix();

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glPushMatrix();
  }

  public void run() {
    while(!Display.isCloseRequested() && !Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) {
      if(Display.isVisible()) {
        processKeyboard();
        processMouse();
        update();
        render();
      }
      else {
        if(Display.isDirty())render();
        try {Thread.sleep(100);}
        catch(InterruptedException ex) {}
      }
      Display.update();
      Display.sync(60);
    }
  }

  public void update() {

    //collisions
    ground=false;c_left=false;c_right=false;c_top=false;
    for(int i=0;i<rects.size();i++){
        if(ground!=true)ground = collisionPoint(squareX+25+hsp,squareY+vsp,rects.get(i));
        if(c_left!=true)c_left = collisionPoint(squareX+hsp,squareY+25+vsp,rects.get(i));
        if(c_right!=true)c_right=collisionPoint(squareX+50+hsp,squareY+25+vsp,rects.get(i));
        if(c_top!=true)c_top   = collisionPoint(squareX+25+hsp,squareY+50+vsp,rects.get(i));
    }
    //gravity
    if(!ground)vsp-=0.2;else vsp=0;

    //movement
    if(k_space&&ground)vsp+=7;
    if(k_left)hsp-=0.2;
    if(k_right)hsp+=0.2;

    //limiters
    if(hsp<-10)hsp=-10;
    if(hsp> 10)hsp= 10;
    if(vsp<-10)vsp=-10;
    if(vsp> 10)vsp= 10;
    if(c_left&&hsp<0)hsp=0;
    if(c_right&&hsp>0)hsp=0;

    //friction
    if(!k_left&&!k_right){
        if(hsp>0.05)hsp-=0.1;
        if(hsp<0.05)hsp+=0.1;
    }
    if(hsp>-0.05&&hsp<0.05)hsp=0;

    //update
    squareX+=hsp;
    squareY+=vsp;
  }

  public boolean collisionPoint(double x,double y,Rectangle rec){
      if(x>(rec.x+rec.w))return false;
      if(y>(rec.y+rec.h))return false;
      if(x<rec.x)return false;
      if(y<rec.y)return false;
      return true;
  }

  public boolean collisionLine(double ax,double ay,double bx,double by,Rectangle rec){
      boolean b=false;
      if(collisionPoint(ax,ay,rec)||collisionPoint(bx,by,rec))return true;
      double len = Math.sqrt((ax-bx)*(ax-bx)+(ay-by)*(ay-by));
      //TODO: NexT.geom.Line implementation
      /*for(int i=1;i<len-2;i+=len/5){
        
      }*/
      return b;
  }
}
